package com.bjy.qa.agent.transport.redis;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * redis 数据库链接池
 */
public class RedisPooledDataSource {
    private static final Logger logger = LoggerFactory.getLogger(RedisPooledDataSource.class);

    private static final Map<String, JedisPool> jedisPoolMap = new ConcurrentHashMap<>(); // 数据源 map
    private String jedisPoolKey; // 数据源 key，在 jedisPoolMap 中用于区分不同的数据源

    private JedisPool jedisPool;

    private String driverClass; // 数据库驱动
    private String url; // 数据库连接字串
    private String port; // 端口号
    private String db; // 数据库
    private String password; // 数据库密码

    /**
     * 构造函数
     * @param driverClass 数据库驱动
     * @param url 数据库连接字串
     * @param port 端口号
     * @param db 数据库
     * @param password 数据库密码
     */
    public RedisPooledDataSource(String driverClass, String url, String port, String db, String password) {
        this.driverClass = driverClass;
        this.url = url;
        this.port = port;
        this.db = db;
        this.password = password;
        this.jedisPoolKey = String.format("%s::%s::%s::%s", url, port, db, password);

        this.jedisPool = getJedisPool();
    }

    /**
     * 获取数据库数据源
     * @return
     */
    private JedisPool getJedisPool() {
        JedisPool jedisPool = (JedisPool) jedisPoolMap.get(this.jedisPoolKey);
        if (jedisPool == null) {
            jedisPool = createJedisPool();
            jedisPoolMap.put(this.jedisPoolKey, jedisPool);
        }
        return jedisPool;
    }

    /**
     * 创建数据源
     * @return
     */
    private JedisPool createJedisPool() {
        if (StringUtils.isBlank(this.driverClass)) {
            String message = String.format("数据库 driverClass 不能为空");
            logger.error(message);
            throw new RuntimeException(message);
        }
        if (StringUtils.isBlank(this.url)) {
            String message = String.format("数据库 HOST / IP 不能为空");
            logger.error(message);
            throw new RuntimeException(message);
        }
        if (StringUtils.isBlank(this.port)) {
            String message = String.format("数据库 port 不能为空");
            logger.error(message);
            throw new RuntimeException(message);
        }
        if (StringUtils.isBlank(this.db)) {
            String message = String.format("数据库 db 不能为空");
            logger.error(message);
            throw new RuntimeException(message);
        }
        try {
            Class.forName(driverClass);
        } catch (ClassNotFoundException e) {
            logger.error("{} 数据库驱动不存在，请确保你在 pom 文件里引入了对应的依赖，或者确认你配置的驱动类名称是否正确", driverClass, e);
            throw new RuntimeException(String.format("数据库驱动 %s 不存在，请确保你在 pom 文件里引入了对应的依赖，或者确认你配置的驱动类名称是否正确", driverClass, e));
        }

        JedisPoolConfig poolConfig = new JedisPoolConfig(); // 配置连接池
        poolConfig.setMaxTotal(8); // 最大连接数
        poolConfig.setMaxIdle(8); // 最大空闲连接
        poolConfig.setMinIdle(0); // 最小空闲连接
        poolConfig.setMaxWaitMillis(1000); // 最长等待时间（ms）

        // 创建连接池对象
        JedisPool jedisPool;
        if (StringUtils.isBlank(this.password)) {
            jedisPool = new JedisPool(poolConfig, this.url, Integer.parseInt(this.port), 1000);
        } else {
            jedisPool = new JedisPool(poolConfig, this.url, Integer.parseInt(this.port), 1000, this.password);
        }

        return jedisPool;
    }

    /**
     * 获取数据库连接
     * @return
     */
    public Jedis getJedis() {
        Jedis jedis = jedisPool.getResource();
        jedis.select(Integer.parseInt(db));
        return jedis;
    }
}
